---
title: "Creating A Kastrax Server"
description: "Configure and customize the Kastrax server with routing, middleware, and other options for your AI agent applications"
---

# Creating A Kastrax Server ✅

When developing or deploying a Kastrax application, it runs as an HTTP server that exposes your agents, workflows, and other functionality as API endpoints. This page explains how to configure and customize the server behavior.

## Server Architecture ✅

Kastrax uses [Ktor](https://ktor.io) as its underlying HTTP server framework. Ktor is a lightweight, high-performance framework specifically designed for Kotlin applications. When you build a Kastrax application, it configures a Ktor-based HTTP server with all the necessary components.

The server provides:

- REST API endpoints for all registered agents
- API endpoints for all registered workflows
- WebSocket support for real-time agent interactions
- Custom route configuration
- Flexible middleware pipeline
- Comprehensive configuration options
- Authentication and authorization support
- CORS configuration

## Server Configuration ✅

You can configure the server using the Kastrax DSL. The server configuration is specified within the `server` block of your Kastrax instance:

```kotlin filename="ServerConfig.kt" showLineNumbers
import ai.kastrax.core.kastrax
import ai.kastrax.server.server

// Create a Kastrax instance with server configuration
val kastraxInstance = kastrax {
    // Configure server
    server {
        port = 8080                // Default: 8080
        host = "0.0.0.0"           // Default: 0.0.0.0
        callTimeout = 30000        // Default: 30000 (30s)
        requestTimeout = 60000     // Default: 60000 (60s)
        enableSwagger = true       // Default: false
        enableOpenAPI = true       // Default: false
        enableCompression = true   // Default: true
        enableMetrics = true       // Default: false
        enableTracing = true       // Default: false
    }

    // Other Kastrax configuration...
}
```

You can also configure the server using environment variables:

```properties filename="application.conf"
kastrax {
    server {
        port = ${?KASTRAX_SERVER_PORT}
        host = ${?KASTRAX_SERVER_HOST}
        callTimeout = ${?KASTRAX_SERVER_CALL_TIMEOUT}
        requestTimeout = ${?KASTRAX_SERVER_REQUEST_TIMEOUT}
    }
}
```

## Custom API Routes ✅

Kastrax automatically generates API routes for all registered agents and workflows. You can also define custom routes to extend the functionality of your server.

Custom routes can be defined within the `server` block using the `routing` function:

```kotlin filename="CustomRoutes.kt" showLineNumbers
import ai.kastrax.core.kastrax
import ai.kastrax.server.server
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*

val kastraxInstance = kastrax {
    server {
        // Configure server settings
        port = 8080

        // Define custom routes
        routing {
            // Simple GET endpoint
            get("/api/status") {
                call.respond(HttpStatusCode.OK, mapOf("status" to "running"))
            }

            // Route with path parameters
            get("/api/agents/{agentId}/info") {
                val agentId = call.parameters["agentId"]
                val agent = kastraxInstance.getAgent(agentId ?: "")

                if (agent != null) {
                    call.respond(HttpStatusCode.OK, mapOf(
                        "name" to agent.name,
                        "description" to agent.description
                    ))
                } else {
                    call.respond(HttpStatusCode.NotFound, mapOf("error" to "Agent not found"))
                }
            }

            // POST endpoint with request body
            post("/api/custom-generate") {
                val request = call.receive<CustomGenerateRequest>()
                val agent = kastraxInstance.getAgent(request.agentId)

                if (agent != null) {
                    val response = agent.generate(request.prompt)
                    call.respond(HttpStatusCode.OK, response)
                } else {
                    call.respond(HttpStatusCode.NotFound, mapOf("error" to "Agent not found"))
                }
            }
        }
    }

    // Other Kastrax configuration...
}

// Request data class
data class CustomGenerateRequest(
    val agentId: String,
    val prompt: String
)
```

You can also define routes in a separate file and include them in your server configuration:

```kotlin filename="Routes.kt" showLineNumbers
import ai.kastrax.core.KastraX
import io.ktor.server.application.*
import io.ktor.server.response.*
import io.ktor.server.routing.*

// Define routes in a separate function
fun Application.configureRoutes(kastraxInstance: KastraX) {
    routing {
        get("/api/custom/health") {
            call.respond(mapOf("status" to "healthy"))
        }

        // More routes...
    }
}
```

Then include them in your server configuration:

```kotlin filename="ServerConfig.kt" showLineNumbers
import ai.kastrax.core.kastrax
import ai.kastrax.server.server

val kastraxInstance = kastrax {
    server {
        // Include custom routes
        install { application ->
            application.configureRoutes(kastraxInstance)
        }
    }
}
```

## CORS Configuration ✅

Kastrax allows you to configure CORS (Cross-Origin Resource Sharing) settings for your server. This is important when your frontend application is hosted on a different domain than your API server.

```kotlin filename="CorsConfig.kt" showLineNumbers
import ai.kastrax.core.kastrax
import ai.kastrax.server.server
import io.ktor.http.*

val kastraxInstance = kastrax {
    server {
        // Configure CORS
        cors {
            allowHost("https://example.com")
            allowHost("https://app.example.com")
            allowMethod(HttpMethod.Get)
            allowMethod(HttpMethod.Post)
            allowMethod(HttpMethod.Options)
            allowHeader(HttpHeaders.ContentType)
            allowHeader(HttpHeaders.Authorization)
            exposeHeader(HttpHeaders.ContentLength)
            maxAgeInSeconds = 3600
            allowCredentials = true
        }
    }

    // Other Kastrax configuration...
}
```

## Middleware Configuration ✅

Kastrax allows you to add custom middleware to the server pipeline. Middleware functions are executed in the order they are defined and can perform tasks like logging, authentication, and request transformation.

```kotlin filename="MiddlewareConfig.kt" showLineNumbers
import ai.kastrax.core.kastrax
import ai.kastrax.server.server
import io.ktor.server.application.*
import io.ktor.server.plugins.callloging.*
import io.ktor.server.plugins.compression.*
import io.ktor.server.plugins.defaultheaders.*
import io.ktor.server.plugins.ratelimit.*
import org.slf4j.event.Level

val kastraxInstance = kastrax {
    server {
        // Install middleware plugins
        install { application ->
            // Add default headers
            application.install(DefaultHeaders) {
                header("X-Engine", "Kastrax")
                header("X-Version", "1.0.0")
            }

            // Add call logging
            application.install(CallLogging) {
                level = Level.INFO
                filter { call -> call.request.path().startsWith("/api") }
            }

            // Add compression
            application.install(Compression) {
                gzip()
                deflate()
            }

            // Add rate limiting
            application.install(RateLimit) {
                global {
                    rateLimiter(limit = 100, refillPeriod = 60000)
                }

                register(RateLimitName("critical-endpoints")) {
                    rateLimiter(limit = 10, refillPeriod = 60000)
                }
            }

            // Custom authentication middleware
            application.intercept(ApplicationCallPipeline.Plugins) {
                val authHeader = call.request.headers["Authorization"]
                if (call.request.path().startsWith("/api/protected") &&
                    (authHeader == null || !authHeader.startsWith("Bearer "))) {
                    throw UnauthorizedException("Invalid or missing authentication token")
                }
            }
        }
    }

    // Other Kastrax configuration...
}

// Custom exception
class UnauthorizedException(message: String) : RuntimeException(message)
```

if you want to add a middleware to a single route, you can also specify that in the registerApiRoute using `registerApiRoute`.

```typescript copy showLineNumbers
registerApiRoute("/my-custom-route", {
  method: "GET",
  middleware: [
    async (c, next) => {
      // Example: Add request logging
      console.log(`${c.req.method} ${c.req.url}`);
      await next();
    },
  ],
  handler: async (c) => {
    // you have access to kastrax instance here
    const kastrax = c.get("kastrax");

    // you can use the kastrax instance to get agents, workflows, etc.
    const agents = await kastrax.getAgent("my-agent");

    return c.json({ message: "Hello, world!" });
  },
});
```

### Middleware Behavior

Each middleware function:

- Receives a Hono context object (`c`) and a `next` function
- Can return a `Response` to short-circuit the request handling
- Can call `next()` to continue to the next middleware or route handler
- Can optionally specify a path pattern (defaults to '/api/\*')
- Inject request specific data for agent tool calling or workflows

## Authentication ✅

Kastrax supports various authentication methods through Ktor's authentication features:

```kotlin filename="AuthConfig.kt" showLineNumbers
import ai.kastrax.core.kastrax
import ai.kastrax.server.server
import io.ktor.server.application.*
import io.ktor.server.auth.*
import io.ktor.server.auth.jwt.*

val kastraxInstance = kastrax {
    server {
        // Configure authentication
        auth {
            // Basic authentication
            basic("auth-basic") {
                realm = "Kastrax Server"
                validate { credentials ->
                    if (credentials.name == "admin" && credentials.password == "password") {
                        UserIdPrincipal(credentials.name)
                    } else {
                        null
                    }
                }
            }

            // JWT authentication
            jwt("auth-jwt") {
                realm = "Kastrax Server"
                verifier(JwtConfig.verifier)
                validate { credential ->
                    if (credential.payload.getClaim("username").asString() != "") {
                        JWTPrincipal(credential.payload)
                    } else {
                        null
                    }
                }
            }
        }
    }

    // Other Kastrax configuration...
}
```

#### CORS Support

```typescript copy
{
  handler: async (c, next) => {
    // Add CORS headers
    c.header("Access-Control-Allow-Origin", "*");
    c.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
    c.header("Access-Control-Allow-Headers", "Content-Type, Authorization");

    // Handle preflight requests
    if (c.req.method === "OPTIONS") {
      return new Response(null, { status: 204 });
    }

    await next();
  };
}
```

#### Request Logging

```typescript copy
{
  handler: async (c, next) => {
    const start = Date.now();
    await next();
    const duration = Date.now() - start;
    console.log(`${c.req.method} ${c.req.url} - ${duration}ms`);
  };
}
```

### Special Kastrax Headers

When integrating with Kastrax Cloud or building custom clients, there are special headers that clients send to identify themselves and enable specific features. Your server middleware can check for these headers to customize behavior:

```typescript copy
{
  handler: async (c, next) => {
    // Check for Kastrax-specific headers in incoming requests
    const isFromKastraxCloud = c.req.header("x-kastrax-cloud") === "true";
    const clientType = c.req.header("x-kastrax-client-type"); // e.g., 'js', 'python'
    const isDevPlayground = c.req.header("x-kastrax-dev-playground") === "true";

    // Customize behavior based on client information
    if (isFromKastraxCloud) {
      // Special handling for Kastrax Cloud requests
    }

    await next();
  };
}
```

These headers have the following purposes:

- `x-kastrax-cloud`: Indicates that the request is coming from Kastrax Cloud
- `x-kastrax-client-type`: Specifies the client SDK type (e.g., 'js', 'python')
- `x-kastrax-dev-playground`: Indicates that the request is from the development playground

You can use these headers in your middleware to implement client-specific logic or enable features only for certain environments.

## Deployment ✅

Since Kastrax builds to a standard Node.js server, you can deploy to any platform that runs Node.js applications:

- Cloud VMs (AWS EC2, DigitalOcean Droplets, GCP Compute Engine)
- Container platforms (Docker, Kubernetes)
- Platform as a Service (Heroku, Railway)
- Self-hosted servers

### Building

Build the application:

```bash copy
# Build from current directory ✅
kastrax build

# Or specify a directory ✅
kastrax build --dir ./my-project
```

The build process:

1. Locates entry file (`src/kastrax/index.ts` or `src/kastrax/index.js`)
2. Creates `.kastrax` output directory
3. Bundles code using Rollup with tree shaking and source maps
4. Generates [Hono](https://hono.dev) HTTP server

See [`kastrax build`](/reference/cli/build) for all options.

## Starting the Server ✅

To start the server, you can use the `kastrax dev` command during development or deploy your application using one of the deployment methods described in the [Deployment](/docs/deployment/deployment) guide.

```kotlin filename="StartServer.kt" showLineNumbers
import ai.kastrax.core.kastrax
import ai.kastrax.server.server

fun main() {
    // Create and configure Kastrax instance
    val kastraxInstance = kastrax {
        server {
            port = 8080
            host = "0.0.0.0"
        }

        // Configure agents, tools, etc.
        agent("assistant") {
            // Agent configuration
        }
    }

    // Start the server
    kastraxInstance.startServer()

    // The server is now running and will block the current thread
    // until the application is stopped
}
```

During development, you can use the `kastrax dev` command, which will automatically restart the server when you make changes to your code.

## Deployment Options ✅

Kastrax supports multiple deployment options:

1. **Standalone JVM Application**: Deploy as a traditional Java application on any server
2. **Docker Container**: Package your application as a Docker container
3. **Kubernetes**: Deploy to a Kubernetes cluster for scalability and resilience
4. **GraalVM Native Image**: Compile to a native executable for maximum performance
5. **Kastrax Cloud**: Use the managed Kastrax Cloud service

See [Deployment Options](/docs/deployment/deployment) for detailed instructions on each deployment method.
